其實所有 React 框架底子都是差不多,主要差別就是架構,今天主要介紹主要檔案們、放所有資料的 app folder,以及 route file naming。
還沒建立 Remix App 的話 npm create-remix@latest
,npm run dev
在 localhost:5173 運行 APP。
這個在最上層的資料夾對應到 React 或是 Next 的 src 資料夾,app 這個名字時刻提醒你他就是個完全為了全端而生的框架,這邊儲存所有 routes、components、css 資料,在 tsconfig.json 裡預設 import 的 ~ PATH 也是解析到這個資料夾,超過 99% 的時間都在編寫這裡的程式碼。
有寫過 next 的應該會很熟悉,route 資料夾基本上是一個檔案一個 route,比較不一樣的是每個檔案裡面都可以直接寫出前端 JSX,以及 loader 與 action 的後端程式碼,讓管理 GET POST PUT DELET 的去向更方便,實務上大家會把 loader action 中的資料庫操作 functions 放在 app/data/*.server.ts
或是 app/db/*.server.ts
資料夾,補足無法統一管理 api 的缺點,這邊的 .server 可以確保裡面的程式碼只會弄在後端而不暴露給前端。
這個就是比較 tricky 的部分,一開始有點難懂,因為 是個 Nested 架構,每下一層的 route 都可以選擇是被上一層包裹的(預設),或是獨立出來。
主要可以分成三種:
<Outlet />
,不然小孩出不來。// Parent
export default function Parent() {
return <Outlet />
}
// Children
export default function Children() {
return <p>Hi im children</p>
}
Parent is not a route
檔案名稱:_parent.children.tsx(example.com/children)
這個跟上面一樣,只是 Parent 不會是一個 route。
Not Children
檔案名稱:parent_.children.tsx(example.com/parent/children)
這樣即便你使用 <Outlet />
也不會出現小孩,使用這個方法的話,Children 就被視為一個獨立的 route。
然後如果 route 是以 $whatEverParam 定義的話,可以在 loader 裡以 params 取得:
export const loader = async ({ params }: LoaderFunctionArgs) => {
const param = params.whatEverParam
}
可能有點複雜,可以玩玩看 Remix Routing Visualization 會比較好懂。